package com.kedll.library;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Application;
import android.content.BroadcastReceiver;
import android.content.ComponentCallbacks;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
import android.databinding.DataBindingUtil;
import android.databinding.ViewDataBinding;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.NonNull;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.LocalBroadcastManager;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.inputmethod.InputMethodManager;

import com.jakewharton.rxbinding2.view.RxView;
import com.kedll.library.dialog.ECAlertDialog;
import com.kedll.library.mvp.BaseView;
import com.kedll.library.util.KeyBoardUtils;
import com.kedll.library.util.MyLog;
import com.trello.rxlifecycle2.android.ActivityEvent;
import com.trello.rxlifecycle2.components.support.RxAppCompatActivity;
import com.umeng.analytics.MobclickAgent;
import com.ypz.bangscreentools.BangScreenTools;

import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.util.concurrent.TimeUnit;

import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.functions.Consumer;


/**
 * @author slj
 * @ClassName: ${NAME}
 * @date 2015/1/5
 * @copyrights 浙江维融电子有限公司
 */
public abstract class KBaseActivity<V extends ViewDataBinding> extends RxAppCompatActivity implements BaseView {
    private static float sRoncompatDennsity;
    private static float sRoncompatScaledDensity;
    public String TAG;
    public MyHandler handler = new MyHandler(this);
    protected int enterAnim = R.anim.slide_right_in;
    protected int exitAnim = R.anim.hold;
    protected BroadcastReceiver internalReceiver;
    protected V mBinding;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        TAG = getClass().getName();

        int conViewRes = getLayout();
        if (conViewRes != 0) {
            mBinding = DataBindingUtil.setContentView(this, conViewRes);
        }

//        MyUtils.setStatusBarColor(this, 0x00000000);
        BangScreenTools.getBangScreenTools().blockDisplayCutout(getWindow());

        setCustomDensity(this, getApplication());
//        ScreenAdapterTools.getInstance().loadView(getWindow().getDecorView());
        initData(savedInstanceState);
        initEvent();
    }

    protected abstract int getLayout();

    private void setCustomDensity(@NonNull Activity activity, final @NonNull Application application) {

        //application
        final DisplayMetrics appDisplayMetrics = application.getResources().getDisplayMetrics();

        if (sRoncompatDennsity == 0) {
            sRoncompatDennsity = appDisplayMetrics.density;
            sRoncompatScaledDensity = appDisplayMetrics.scaledDensity;
            application.registerComponentCallbacks(new ComponentCallbacks() {
                @Override
                public void onConfigurationChanged(Configuration newConfig) {
                    if (newConfig != null && newConfig.fontScale > 0) {
                        sRoncompatScaledDensity = application.getResources().getDisplayMetrics().scaledDensity;
                    }
                }

                @Override
                public void onLowMemory() {

                }
            });
        }

        //计算宽为360dp 同理可以设置高为640dp的根据实际情况
        final float targetDensity = appDisplayMetrics.widthPixels / 360;
        final float targetScaledDensity = targetDensity * (sRoncompatScaledDensity / sRoncompatDennsity);
        final int targetDensityDpi = (int) (targetDensity * 160);

        appDisplayMetrics.density = targetDensity;
        appDisplayMetrics.densityDpi = targetDensityDpi;
        appDisplayMetrics.scaledDensity = targetScaledDensity;

        //activity
        final DisplayMetrics activityDisplayMetrics = activity.getResources().getDisplayMetrics();

        activityDisplayMetrics.density = targetDensity;
        activityDisplayMetrics.densityDpi = targetDensityDpi;
        activityDisplayMetrics.scaledDensity = targetScaledDensity;


    }

    protected abstract void initData(Bundle savedInstanceState);

    protected abstract void initEvent();

    @Override
    protected void onResume() {
        super.onResume();
        MobclickAgent.onResume(this);
    }

    @Override
    protected void onPause() {
        super.onPause();
        MobclickAgent.onPause(this);
        if (isFinishing()) {
            try {
                LocalBroadcastManager.getInstance(getApplication()).unregisterReceiver(internalReceiver);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    protected void onDestroy() {
        fixInputMethodManagerLeak(this);
        MyLog.getInstance().dismissDialog();
        MyLog.getInstance().setDismissListener(null);
        handler.removeCallbacksAndMessages(null);
        handler = null;
        super.onDestroy();
    }

    public static void fixInputMethodManagerLeak(Context destContext) {
        if (destContext == null) {
            return;
        }

        InputMethodManager imm = (InputMethodManager) destContext.getSystemService(Context.INPUT_METHOD_SERVICE);
        if (imm == null) {
            return;
        }

        String[] arr = new String[]{"mCurRootView", "mServedView", "mNextServedView"};
        Field f;
        Object objGet;
        for (String param : arr) {
            try {
                f = imm.getClass().getDeclaredField(param);
                if (!f.isAccessible()) {
                    f.setAccessible(true);
                } // author: sodino mail:sodino@qq.com
                objGet = f.get(imm);
                if (objGet != null && objGet instanceof View) {
                    View vGet = (View) objGet;
                    if (vGet.getContext() ==
                            destContext) { // 被InputMethodManager持有引用的context是想要目标销毁的
                        f.set(imm, null); // 置空，破坏掉path to gc节点
                    } else {
                        // 不是想要目标销毁的，即为又进了另一层界面了，不要处理，避免影响原逻辑,也就不用继续for循环了
                        break;
                    }
                }
            } catch (Throwable t) {
                t.printStackTrace();
            }
        }
    }

    /**
     * 设置状态栏背景色 个别界面有不一样的背景色,可重写此方法
     *
     * @return 背景色
     */
    protected int getColor() {
        return ContextCompat.getColor(this, R.color.statubar_color);
    }

    /**
     * 切换到指定的Activity，有数据传递
     *
     * @param bundle 传递的数据
     * @param cls    指定的Activity
     */
    public void startActivityNoAnim(Bundle bundle, Class<?> cls) {
        Intent intent = getIntent(cls);
        intent.putExtras(bundle);
        startActivity(intent);
    }

    @NonNull
    private Intent getIntent(Class<?> cls) {
        Intent intent = new Intent();
        intent.setClass(this, cls);
        return intent;
    }

    public void startActivityNoAnim(Class<?> cls) {
        Intent intent = getIntent(cls);
        startActivity(intent);
    }

    /**
     * 切换到指定的Activity， 无传递数据
     *
     * @param cls 指定的Activity
     */
    public void startActivity(Class<?> cls) {
        Intent intent = getIntent(cls);
        startActivity(intent);
        overridePendingTransition(enterAnim, exitAnim);
    }

    /**
     * 切换到指定的Activity，有数据传递
     *
     * @param bundle 传递的数据
     * @param cls    指定的Activity
     */
    public void startActivity(Bundle bundle, Class<?> cls) {
        Intent intent = getIntent(cls);
        intent.putExtras(bundle);
        startActivity(intent);
        overridePendingTransition(enterAnim, exitAnim);
    }

    /**
     * 切换到指定的Activity，无传递数据，但需要返回结果
     *
     * @param cls         指定的Activity
     * @param requestCode 返回结果代码
     */
    public void startActivityForResult(Class<?> cls, int requestCode) {
        Intent intent = getIntent(cls);
        startActivityForResult(intent, requestCode);
        overridePendingTransition(enterAnim, exitAnim);
    }

    /**
     * 切换到指定的Activity，传递数据，需要返回结果
     *
     * @param bundle      传递数据
     * @param cls         指定的Activity
     * @param requestCode 返回结果代码
     */
    public void startActivityForResult(Bundle bundle, Class<?> cls, int requestCode) {
        Intent intent = getIntent(cls);
        intent.putExtras(bundle);
        startActivityForResult(intent, requestCode);
        overridePendingTransition(enterAnim, exitAnim);
    }

    protected final void registerReceiver(String[] actionArray) {
        if (actionArray == null) {
            return;
        }
        IntentFilter intentfilter = new IntentFilter();
        for (String action : actionArray) {
            intentfilter.addAction(action);
        }
        if (internalReceiver == null) {
            internalReceiver = new InternalReceiver();
        }
        LocalBroadcastManager.getInstance(getApplication()).registerReceiver(internalReceiver, intentfilter);
    }

    protected void sendBroadcast(String action) {
        LocalBroadcastManager.getInstance(getApplication()).sendBroadcast(new Intent(action));
    }

    @Override
    public void sendBroadcast(Intent intent) {
        LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent);
    }

    /**
     * 如果子界面需要拦截处理注册的广播
     * 需要实现该方法
     *
     * @param context
     * @param intent
     */
    protected void handleReceiver(Context context, Intent intent) {
        // 广播处理
        if (intent == null) {
            return;
        }
    }

    @SuppressLint("CheckResult")
    public void finishDelay() {
        Observable.timer(2, TimeUnit.SECONDS)
                .observeOn(AndroidSchedulers.mainThread())
                .compose(this.bindUntilEvent(ActivityEvent.DESTROY))
                .subscribe(new Consumer<Long>() {
                    @Override
                    public void accept(Long aLong) throws Exception {
                        KBaseActivity.this.finish();
                    }
                });
    }

    @Override
    public void finish() {
        KeyBoardUtils.hideKeyBoard(this);
        super.finish();
    }

    public void finish(boolean isFinish) {
        if (!isFinish) {
            if (isExit()) {
                ECAlertDialog dialog = ECAlertDialog.buildAlert(this, R.string.string_exit_before_edit, android.R.string.cancel, R.string.exit, null, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog1, int which) {
                        KBaseActivity.this.finish();
                    }
                });
                dialog.setTitle(R.string.app_tip);
                dialog.show();
            } else {
                finish();
            }
        } else {
            finish();
        }
    }

    protected boolean isExit() {
        return false;
    }

    protected void handlerMessage(Message msg) {
        if (msg.obj == null) {
            MyLog.getInstance().dismissDialog();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    @SuppressLint("CheckResult")
    public void onClicked(View view, Consumer<Object> consumer) {
        RxView.clicks(view)
                .compose(bindToLifecycle())
                .throttleFirst(500, TimeUnit.MILLISECONDS)
                .subscribe(consumer);

    }

    @Override
    public void showLoad(String msg) {
        MyLog.getInstance().showProgressDialog(this, msg);
    }

    @Override
    public void hideLoad() {
        MyLog.getInstance().dismissDialog();
    }

    @Override
    public Context getContext() {
        return this;
    }

    public static class MyHandler extends Handler {
        WeakReference<KBaseActivity> activity;

        MyHandler(KBaseActivity fragment) {
            // TODO Auto-generated constructor stub
            this.activity = new WeakReference<>(fragment);
        }

        @Override
        public void handleMessage(Message msg) {
            // TODO Auto-generated method stub
            super.handleMessage(msg);
            KBaseActivity fragment = this.activity.get();
            if (fragment != null) {
                fragment.handlerMessage(msg);
            }
        }
    }

    // Internal calss.
    private class InternalReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent == null || intent.getAction() == null) {
                return;
            }
            handleReceiver(context, intent);
        }
    }
}
